#include "CESParser.h"
#include "CTSBuilder.h"
#include "CPESBuilder.h"
#include "CAUBuilder.h"
#include "CVlcDelegator.h"
#include "CFileExporter.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream> 
#include <string>
#include <sstream>

using namespace std;

#ifdef WIN_32
//////////////TEMP- check for memory leaks
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
//////////////end TEMP
#endif

void printHelp(string sProgramName);

/**
General variables
*/
string sInputFileName = "1080i.mpg";
unsigned int nAudioPID = 68;//52;//68
unsigned int nVideoPID = 65;//49;//65;

/**
File variables
*/
bool bWriteToFile = false;
string sAudioFileName = "audio_output.au";
string sVideoFileName = "video_output.au";

/**
Socket variables
*/
string sVlcIP = "127.0.0.1";
int nAudioPort = 1234;
int nVideoPort = 1235;

bool bStaticSending = false;

/**
Error Handeling
*/
CPESBuilder::EFixMode eFixMode = CPESBuilder::allowAny;

/**
Convert a std string into an integer
*/
int str2int (const string &str) {
	stringstream ss(str);
	int n;
	ss >> n;
	return n;
}

void parseInputParameters(int argc, char *argv[])
{
	string sProgramName(argv[0]);
	//print help
	if (argc == 2){
		string sKey(argv[1]);
		if (0 == sKey.compare("-help")){
			printHelp(sProgramName);
		}
	}
	//Check that nmber of params is even
	if (argc%2 == 0){
		cout << "Number of parameters is not even. exiting" << endl;
	}
	//parse params
	for (int i=1; i<argc; i+=2){
		string sKey(argv[i]);
		string sValue(argv[i+1]);
		if (0 == sKey.compare("-inputFile")){
			sInputFileName = sValue;
		}
		else if (0 == sKey.compare("-audioPid")){
			nAudioPID = str2int(sValue);
		}
		else if (0 == sKey.compare("-videoPid")){
			nVideoPID = str2int(sValue);
		}
		else if (0 == sKey.compare("-vlcIP")){
			bWriteToFile = false;
			sVlcIP = sValue;
		}
		else if (0 == sKey.compare("-audioFile")){
			bWriteToFile = true;
			sAudioFileName = sValue;
		}
		else if (0 == sKey.compare("-videoFile")){
			bWriteToFile = true;
			sVideoFileName = sValue;
		}
		else if (0 == sKey.compare("-audioPort")){
			nAudioPort = str2int(sValue);
		}
		else if (0 == sKey.compare("-videoPort")){
			nVideoPort = str2int(sValue);
		}
		else if (0 == sKey.compare("-static")){
			bStaticSending = (sValue.compare("true") == 0);
		}
		else if (0 == sKey.compare("-fixMode")){
			if (0 == sValue.compare("none"))
				eFixMode = CPESBuilder::none;
			else if (0 == sValue.compare("allowAny"))
				eFixMode = CPESBuilder::allowAny;
			else if (0 == sValue.compare("allowFew"))
				eFixMode = CPESBuilder::allowFew;
			else if (0 == sValue.compare("considerLength"))
				eFixMode = CPESBuilder::considerLength;
		}
		else{
			cout << "parameter "<<sKey <<" does not supported. See Help (" << sProgramName << " -help)"<<endl;
		}
	}
}

void temp()
{
	set<unsigned int> pids;
	pids.insert(nVideoPID);
	pids.insert(nAudioPID);
	IESParser* cEsParser = new CESParser(sInputFileName);
	ITSBuilder* cTSBuilder = new CTSBuilder(pids, !bStaticSending);
	IPESBuilder* cPESBuilder = new CPESBuilder(pids, eFixMode);
	IAUBuilder* cAUBuilder = new CAUBuilder(nAudioPID, nVideoPID);
	IOutputStreamer* cOutputStreamer;
	if (bWriteToFile)
		cOutputStreamer = new CFileExporter(sAudioFileName, sVideoFileName);
	else
		cOutputStreamer = new CVlcDelegator(sVlcIP, nAudioPort, nVideoPort);

	while (cEsParser->readData()){
		cTSBuilder->findTS(cEsParser);
		cPESBuilder->buildPes(cTSBuilder);
		cAUBuilder->BuildAu(cPESBuilder);
		if (!bStaticSending)
			cOutputStreamer->outputAUs(cAUBuilder);
	}
	cAUBuilder->BuildAu(cPESBuilder);
	cOutputStreamer->outputAUs(cAUBuilder);

	delete cEsParser;
	delete cTSBuilder;
	delete cPESBuilder;
	delete cAUBuilder;
	delete cOutputStreamer;
}
/**
Main function
*/
int main(int argc, char *argv[])
{	
	//initialize parameters according to the input
	parseInputParameters(argc, argv);
	temp();

#ifdef WIN_32
	//temp- for debuging, print memoryleaks
	_CrtDumpMemoryLeaks();
//	getchar();
#endif
}


/**
Print Usage.
*/
void printHelp(string sProgramName)
{
	string sHelpString = "Usage: "+ sProgramName+ " [params]";
	sHelpString += "optional parameters are:\n";
	sHelpString += "-inputFile <file_name>: The name of the input file.\n";
	sHelpString += "-audioPid <PID_number>: The number of the audio PID in the input file.\n";
	sHelpString += "-videoPid <PID_number>: The number of the video PID in the input file.\n";
	sHelpString += "-fixMode <none/allowAny/allowFew/considerLength>: Error handeling mode.\n";
	sHelpString += "\n";
	sHelpString += "If Using VLC, specify the following parameters:\n";
	sHelpString += "-t-vlcIP <ip>: The IP of the computer where the VLC is running\n";
	sHelpString += "\t-audioPort <port_number>: The number of the audio port.\n";
	sHelpString += "\t-videoPort <port_number>: The number of the video port.\n";
	sHelpString += "\n";
	sHelpString += "If Using Output File, specify the following parameters:\n";
	sHelpString += "\t-audioFile <file_name>: The name of the output audio file.\n";
	sHelpString += "\t-videoFile <file_name>: The name of the output video file.\n";

	cout << sHelpString;
	exit (0);
}
